#include "CStorageMgr.h"
#include "MsgComm.pb.h"
#include "MsgStorage.pb.h"
#include "MsgEquipInfo.pb.h"
#include "../mainctrl.h"
#include "../equip/CEquipMgr.h"
#include "commmsg.h"
int CStorageMgr::InitData(CUserStorage& stUserStorage, StorageData& stData)
{
    stUserStorage.Clear();

    stData._shMaxBagGridCount = CT_MAX(stData._shMaxBagGridCount, SYS_DEFAULT_GRID_NUM_BAG);    

    stUserStorage.SetMaxBagGridCount(stData._shMaxBagGridCount);
    stUserStorage.SetMaxWareHouseGridCount(stData._shMaxWareHouseGridCount);
    for (int i = 0; i < stData._astGridData.Size(); ++i)
    {
        if (stData._astGridData[i].IsEmpty())
        {
            continue;
        }

        CStorageGrid stGrid;
        stGrid._stKey._ucItemType = stData._astGridData[i]._ucItemType;
        stGrid._stKey._uiItemID = stData._astGridData[i]._uiItemID;
        stGrid._stKey._bIsInBag = (stData._astGridData[i]._ucIsInBag == 1);
        stGrid._stKey._usStorePos = stData._astGridData[i]._usStorePos;
        stGrid._shCount = stData._astGridData[i]._shItemCount;
        stGrid._iInvalidTime = stData._astGridData[i]._iInvalidTime;

        CItemConfigData stConfigData;
        int iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetConfig(stGrid._stKey._ucItemType, stGrid._stKey._uiItemID, stConfigData);
        CHECK_RETURN(iRet);

        stGrid._iPosValue = stConfigData._iPosValue;
        stGrid._shMaxPerGrid = stConfigData._shMaxCountPerGrid;

        iRet = stUserStorage.AddGrid(stGrid);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CStorageMgr::GetData(CUserStorage& stUserStorage, StorageData& stData)
{
    stData._astGridData.Clear();

    stUserStorage._shMaxBagGridCount = CT_MAX(stUserStorage._shMaxBagGridCount, SYS_DEFAULT_GRID_NUM_BAG);    

    stData._shMaxBagGridCount = stUserStorage._shMaxBagGridCount;
    stData._shMaxWareHouseGridCount = stUserStorage._shMaxWareHouseGridCount;
    CStorageHash& stStorageHash = stUserStorage._stStorageHash;
    for (int iIndex = stStorageHash.GetHeadIndex();
        iIndex >= 0; iIndex = stStorageHash.GetNextIndex(iIndex))
    {
        StorageItemData stSingleData;
        stSingleData._ucItemType = stStorageHash[iIndex]._stKey._ucItemType;
        stSingleData._uiItemID = stStorageHash[iIndex]._stKey._uiItemID;
        stSingleData._shItemCount = stStorageHash[iIndex]._shCount;
        stSingleData._usStorePos = stStorageHash[iIndex]._stKey._usStorePos;
        stSingleData._ucIsInBag = stStorageHash[iIndex]._stKey._bIsInBag ? 1 : 0;
        stSingleData._iInvalidTime = stStorageHash[iIndex]._iInvalidTime;

        stData._astGridData.AddOneItem(stSingleData);
    }

    return 0;
}

void CStorageMgr::UpdateGridCount (CUserStorage& stUserStorage, short sRoleLevel, bool & bNewUnlocked)
{
    unsigned char ucMaxGridCount = 0;
    unsigned char ucCurGridCount = 0;

    bNewUnlocked = false;

#if 0
    GetGridCount (sRoleLevel, STORAGE_TYPE_BAG, ucMaxGridCount);
    ucCurGridCount = stUserStorage.GetMaxBagGridCount();
    if (ucMaxGridCount > ucCurGridCount)
    {
        bNewUnlocked = true;
        stUserStorage.SetMaxBagGridCount(ucMaxGridCount);
    }
#endif

    GetGridCount (sRoleLevel, STORAGE_TYPE_WARE, ucMaxGridCount);
    ucCurGridCount = stUserStorage.GetMaxWareHouseGridCount();
    if (ucMaxGridCount > ucCurGridCount)
    {
        bNewUnlocked = true;
        stUserStorage.SetMaxWareHouseGridCount(ucMaxGridCount);
    }
}

int CStorageMgr::GetGridCount (short sRoleLevel, unsigned char ucStorageType, unsigned char & ucGridCount)
{
    if (sRoleLevel < 40)
    {
        ucGridCount = (ucStorageType == STORAGE_TYPE_BAG) ? SYS_DEFAULT_GRID_NUM_BAG : SYS_DEFAULT_GRID_NUM_WAREHOUSE;
    }

    if (STORAGE_TYPE_BAG == ucStorageType)
    {
        ucGridCount = SYS_DEFAULT_GRID_NUM_BAG + (((sRoleLevel - 40)/10 + 1) * 3);
        ucGridCount = (ucGridCount < MAX_BAG_GRID_COUNT) ? ucGridCount : MAX_BAG_GRID_COUNT;
    }

    if (STORAGE_TYPE_WARE == ucStorageType)
    {
        ucGridCount = SYS_DEFAULT_GRID_NUM_WAREHOUSE + (((sRoleLevel - 40)/10 + 1) * 6);
        ucGridCount = (ucGridCount < MAX_WAREHOUSE_GRID_COUNT) ? ucGridCount : MAX_WAREHOUSE_GRID_COUNT;
    }

    return 0;
}

int CStorageMgr::GetUnLockGridPrice (CUserStorage& stUserStorage, unsigned char ucStorageType, unsigned short & usGoldPrice)
{   
    usGoldPrice = 0;

    if (STORAGE_TYPE_BAG == ucStorageType)
    {
        int iGridCount = stUserStorage.GetMaxBagGridCount();
        if (MAX_BAG_GRID_COUNT == iGridCount)  //已经全部解锁了
        {            
            return 0;
        }
    
        unsigned short ausPrice[] = {5, 10, 15, 20, 30, 40, 50};
        int iIndex = (iGridCount - SYS_DEFAULT_GRID_NUM_BAG) / 6;
        if (iIndex >= 0 && (iIndex < int(sizeof(ausPrice) / sizeof(ausPrice[0]))))
        {
            usGoldPrice = ausPrice[iIndex];
        }
    }

    if (STORAGE_TYPE_WARE == ucStorageType)
    {
        int iGridCount = stUserStorage.GetMaxWareHouseGridCount();
        if (MAX_WAREHOUSE_GRID_COUNT == iGridCount)
        {    
            return 0;
        }

        unsigned short ausPrice[] = {10, 30, 60, 100, 150, 200};
        int iIndex = (iGridCount - SYS_DEFAULT_GRID_NUM_WAREHOUSE) / 6;
        if (iIndex >= 0 && (iIndex < int(sizeof(ausPrice) / sizeof(ausPrice[0]))))
        {
            usGoldPrice = ausPrice[iIndex];
        }
    }
    
    return 0;
}

int CStorageMgr::UnLockGrid (CUserStorage& stUserStorage, unsigned char ucStorageType)
{
    if (STORAGE_TYPE_BAG == ucStorageType)
    {
        stUserStorage.SetMaxBagGridCount(stUserStorage.GetMaxBagGridCount() + 1);
    }

    if (STORAGE_TYPE_WARE == ucStorageType)
    {
        stUserStorage.SetMaxWareHouseGridCount(stUserStorage.GetMaxWareHouseGridCount() + 1);
    }

    return 0;
}

int CStorageMgr::GetBagList(CUserStorage& stUserStorage, T_STORAGE_GRIDS& astStorageGrid)
{
    int iRet = 0;

    for (int i = stUserStorage.GetBagHeadIndex();
        i >= 0;)
    {
        CStorageGrid stGrid;
        iRet = stUserStorage.GetGridInfoByIndex(i, stGrid);
        CHECK_RETURN(iRet);

        astStorageGrid.AddOneItem(stGrid);

        i = stUserStorage.GetBagNextIndex(stGrid._stKey._usStorePos);
    }

    return 0;
}

int CStorageMgr::GetWareHouseList(CUserStorage& stUserStorage, T_STORAGE_GRIDS& astStorageGrid)
{
    int iRet = 0;

    for (int i = stUserStorage.GetWareHouseHeadIndex();
        i >= 0; )
    {
        CStorageGrid stGrid;
        iRet = stUserStorage.GetGridInfoByIndex(i, stGrid);
        CHECK_RETURN(iRet);

        astStorageGrid.AddOneItem(stGrid);

        i = stUserStorage.GetWareHouseNextIndex(stGrid._stKey._usStorePos);
    }

    return 0;
}

int CStorageMgr::GetGridInfoByPos(CUserStorage& stUserStorage, bool bIsInBag, unsigned short usPos, CStorageGrid& stGrid)
{
    return stUserStorage.GetGridInfoByPos(bIsInBag, usPos, stGrid);
}

//取出物品
int CStorageMgr::TakeOutGrid(CUserStorage& stUserStorage,  unsigned short usPos, CStorageGrid& stGrid)
{
    return stUserStorage.TakeOutGrid(true, usPos, stGrid);
}

//替换背包格子
int CStorageMgr::ReplaceGrid(CUserStorage& stUserStorage, bool bIsInBag, unsigned short usPos, CStorageGrid & stNewGrid)
{
    return stUserStorage.ReplaceGrid(bIsInBag, usPos, stNewGrid);
}

int CStorageMgr::TryAddItem(CUserStorage& stUserStorage, unsigned char ucItemType, unsigned int uiItemID, short& shCount)
{
    return stUserStorage.AddAllItem(ucItemType, uiItemID, shCount, true);
}

int CStorageMgr::AddItem( CUserStorage& stUserStorage, unsigned char ucItemType, unsigned int uiItemID, short shCount)
{
    if (!stUserStorage.IsAddible(ucItemType, uiItemID, shCount, true))
    {
        return ERROR_STORAGE_ADD_FULL;
    }

    return stUserStorage.AddAllItem(ucItemType, uiItemID, shCount, true);
}

//获取物品数量
int CStorageMgr::GetItemCount(CUserStorage& stUserStorage, unsigned char ucItemType, unsigned int uiItemID)
{
    return stUserStorage.GetItemCount(ucItemType, uiItemID);
}

//消耗物品
int CStorageMgr::TakeOutItem(CUserStorage& stUserStorage, unsigned char ucItemType, unsigned int uiItemID, int iCount)
{
    if (GetItemCount(stUserStorage, ucItemType, uiItemID) < iCount)
    {
        return ERROR_STORAGE_TAKE_OUT_TOO_MANY_ITEM;
    }

    short shLeftCount = 0;
    int iRet = stUserStorage.TakeOutItem(ucItemType, uiItemID, iCount, shLeftCount);
    CHECK_RETURN(iRet);

    if (0 != shLeftCount)
    {
        CT_ERROR(("%d, %d, %d", stUserStorage._uiGID, iCount, shLeftCount));
        return ERROR_TAKE_OUT_NOT_ENGOUGH;
    }

    return 0;
}

int CStorageMgr::TakeOutItem(CUserStorage& stUserStorage, unsigned short usBagPos, short shCount)
{
    return  stUserStorage.TakeOutItemOnGird(true, usBagPos, shCount);
}

//排序
int CStorageMgr::SortStorage(CUserStorage& stUserStorage, bool bIsSortBag)
{
    return stUserStorage.SortStorage(bIsSortBag);
}

//合并背包
int CStorageMgr::MergeToWareHouse(CUserStorage& stUserStorage)
{
    return stUserStorage.MergeToWareHouse();
}

void CStorageMgr::GetStorageInfo(unsigned char ucBagType, unsigned int uiGID, CUserStorage& stUserStorage, MsgAnsUserStorageInfo& stAns)
{
    T_STORAGE_GRIDS astStorageGrid;

    stAns.set_gid(uiGID);
    stAns.set_storage_type(ucBagType);

    switch (ucBagType)
    {
    case STORAGE_TYPE_BAG:
        {
            stAns.set_grid_total_num(MAX_BAG_GRID_COUNT);
            stAns.set_grid_default_num(SYS_DEFAULT_GRID_NUM_BAG);
            stAns.set_grid_unlocked_num(stUserStorage.GetMaxBagGridCount() - SYS_DEFAULT_GRID_NUM_BAG);
            GetBagList(stUserStorage, astStorageGrid);
        }
        break;
    case STORAGE_TYPE_WARE:
        {
            stAns.set_grid_total_num(MAX_WAREHOUSE_GRID_COUNT);
            stAns.set_grid_default_num(SYS_DEFAULT_GRID_NUM_WAREHOUSE);
            stAns.set_grid_unlocked_num(stUserStorage.GetMaxWareHouseGridCount() - SYS_DEFAULT_GRID_NUM_WAREHOUSE);
            GetWareHouseList(stUserStorage, astStorageGrid);
        }
        break;
    case STORAGE_TYPE_GROUD:
        {
            stAns.set_grid_total_num(MAX_GROUD_GRID_COUNT);
            stAns.set_grid_default_num(MAX_GROUD_GRID_COUNT);
            stAns.set_grid_unlocked_num(0);
            GetBagList(stUserStorage, astStorageGrid);
        }
        break;

    case STORAGE_TYPE_CLAN:
        {
            stAns.set_grid_total_num(MAX_CLAN_STORAGE_COUNT);
            stAns.set_grid_default_num(MAX_CLAN_STORAGE_COUNT);
            stAns.set_grid_unlocked_num(0);
            GetBagList(stUserStorage, astStorageGrid);
        }
        break;
    }

    for (int i = 0; i < astStorageGrid.Size(); ++i)
    {
        MsgGridItemInfo* pstGridItemInfo = stAns.add_grid_items();
        GetGridInfo(uiGID, astStorageGrid[i], *pstGridItemInfo);
    }
}

void CStorageMgr::SendScrollDetailInfoToFront(CPlayerOnlineData& stPlayerOnlineData, unsigned short usScrollId, PBMsgHead stMsgHead, CTLib::CEnpNetHead& stEnpHead)
{
    MsgAnsItemDetailInfos stAns;
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgid(ID_MAIN_GET_ITEM_DETAIL_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    GetScrollDetailInfo(stPlayerOnlineData, usScrollId, *(stAns.mutable_scroll_info()));

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}


void CStorageMgr::GetEquipGridInfo (unsigned int uiGid, CStorageGrid & stStorageGrid, MsgGridItemInfo & stGridItem)
{
    if (ITEM_TYPE_EQUIP != stStorageGrid._stKey._ucItemType)
    {
        CT_ERROR(("%d", stStorageGrid._stKey._ucItemType));
        return ;
    }

    unsigned short usEquipConfigID;
    CMainCtrl::m_pstMain->m_stEquipMgr.GetConfigIdByEquipId(stStorageGrid._stKey._uiItemID, usEquipConfigID);

    stGridItem.Clear();    
    stGridItem.set_item_type(stStorageGrid._stKey._ucItemType);
    stGridItem.set_item_config_id(usEquipConfigID);
    stGridItem.set_item_count(stStorageGrid._shCount);
    stGridItem.set_item_store_pos(stStorageGrid._stKey._usStorePos);
    stGridItem.set_invalid_time(stStorageGrid._iInvalidTime);
    if (usEquipConfigID != stStorageGrid._stKey._uiItemID)
    {
        uint64 aux = CT_UINT64_MAKE(uiGid, stStorageGrid._stKey._uiItemID);
        stGridItem.set_item_aux_info(CTStringUtils::Uint64ToString(aux, 10));
    }    
}


void CStorageMgr::GetGridInfo(unsigned int uiGid, CStorageGrid & stStorageGrid, MsgGridItemInfo & stGridItem)
{
    if (stStorageGrid._stKey._ucItemType == ITEM_TYPE_EQUIP)
    {
        GetEquipGridInfo (uiGid, stStorageGrid, stGridItem);
    }
    else
    {
        stGridItem.Clear();
        stGridItem.set_item_store_pos(stStorageGrid._stKey._usStorePos);
        stGridItem.set_item_type(stStorageGrid._stKey._ucItemType);
        stGridItem.set_item_count(stStorageGrid._shCount);
        stGridItem.set_invalid_time(stStorageGrid._iInvalidTime);
        stGridItem.set_item_config_id(stStorageGrid._stKey._uiItemID);
    }
}

int CStorageMgr::GetScrollDetailInfo (CPlayerOnlineData & stPlayerOnlineData, unsigned short usScrollId, MsgScrollDetailInfo & stScrollInfo)
{
    CScrollConfigData stScrollConfig;
    unsigned int uiItemCnt;
    MsgItemSynInfo * pstSynItem;
    int iRet;
    CUserStorage & stUserStorage = stPlayerOnlineData._stUserStorage;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetScrollConfig(usScrollId, stScrollConfig);
    CHECK_RETURN(iRet);

    if (ITEM_TYPE_EQUIP == stScrollConfig._ucNewItemType)
    {
        uiItemCnt = GetItemCount(stUserStorage, ITEM_TYPE_EQUIP, stScrollConfig._usOldEquipConfigID);
        pstSynItem = stScrollInfo.add_items();
        pstSynItem->set_item_type(ITEM_TYPE_EQUIP);
        pstSynItem->set_item_cfg_id(stScrollConfig._usOldEquipConfigID);
        pstSynItem->set_need_item_cnt(1);
        pstSynItem->set_cur_item_cnt(uiItemCnt);
    }

    for (int i = 0; i < stScrollConfig._astMaterial.Size(); i++)
    {
        pstSynItem = stScrollInfo.add_items();
        GetScrollSynInfo(stUserStorage, stScrollConfig._astMaterial[i], *pstSynItem);
        CInstanceId stDropInstanceId;
        CMainCtrl::m_pstMain->m_stInstanceMgr.GetDropInstanceID(ITEM_TYPE_MATERIAL, stScrollConfig._astMaterial[i]._usMaterialId,
                                  stPlayerOnlineData._stUserInstance._stInstanceData._stHasOpenedInstanceData, stDropInstanceId);
        pstSynItem->set_instance_type(stDropInstanceId._ucInstanceType);
        pstSynItem->set_instance_id(stDropInstanceId._usInstanceID);
    }

    stScrollInfo.set_scroll_cfg_id(stScrollConfig._usSrollConfigID);
    return 0;
}

void CStorageMgr::GetScrollSynInfo(CUserStorage &stUserStorage, CScrollMaterial & stNeedMaterial, MsgItemSynInfo & stSynItemInfo)
{
    unsigned int uiItemCnt = GetItemCount(stUserStorage, ITEM_TYPE_MATERIAL, stNeedMaterial._usMaterialId);
    stSynItemInfo.Clear();
    stSynItemInfo.set_item_type(ITEM_TYPE_MATERIAL);
    stSynItemInfo.set_item_cfg_id(stNeedMaterial._usMaterialId);
    stSynItemInfo.set_need_item_cnt(stNeedMaterial._usMaterialCnt);
    stSynItemInfo.set_cur_item_cnt(uiItemCnt);
}

bool CStorageMgr::IsScrollMaterialEnough(CUserStorage &stUserStorage, unsigned short usScrollConfigId)
{
    if (stUserStorage.CheckScrollMaterial(usScrollConfigId))
    {
        return false;
    }

    return true;
}

//获取金币合成时,所需金币
int CStorageMgr::GetScrollGoldCost(CUserStorage &stUserStorage, unsigned short usScrollConfigId, int &iGoldCost)
{
    return stUserStorage.GetScrollGoldCost(usScrollConfigId, iGoldCost);
}

int CStorageMgr::MakeItem(CUserStorage& stUserStorage, CStorageGrid & stScrollGrid, unsigned char ucOpType, bool bScrollNecessary)
{
    return stUserStorage.MakeItem(stScrollGrid, ucOpType, bScrollNecessary);
}

int CStorageMgr::CombineCrystal (CUserStorage& stUserStorage, unsigned char ucOldCrystalId, unsigned char ucCombinedId)
{
    return stUserStorage.CombineCrystal(ucOldCrystalId, ucCombinedId);
}

int CStorageMgr::OneKeyCrystal (CPlayerDetailInfo & stPlayerDetailInfo, CUserStorage& stUserStorage, unsigned char ucCombinedLevel)
{
    return stUserStorage.OneKeyCrystal(stPlayerDetailInfo, ucCombinedLevel);
}

void CStorageMgr::SendInfoToFront(unsigned char ucBagType, unsigned int uiGID, CUserStorage& stUserStorage, PBMsgHead stMsgHead, CEnpNetHead& stEnpHead)
{
    MsgAnsUserStorageInfo stAns;
    GetStorageInfo(ucBagType, uiGID, stUserStorage, stAns);

    stMsgHead.set_msgid(ID_MAIN_GET_USER_STORAGE_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stMsgHead.set_msgact(0);
    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}

int CStorageMgr::DecomposeCrystal (CPlayerBaseInfo & stPlayerBaseInfo, CPlayerOnlineData & stPlayerOnlineData, unsigned short usBagPos, CStorageGrid & stResult)
{
    CStorageGrid stGrid;
    int iRet = CMainCtrl::m_pstMain->m_stStorageMgr.GetGridInfoByPos(stPlayerOnlineData._stUserStorage, true, usBagPos, stGrid);
    CHECK_RETURN(iRet);

    if (ITEM_TYPE_CRYSTAL != stGrid._stKey._ucItemType )
    {
        CT_ERROR(("%d, %d", usBagPos, stGrid._stKey._ucItemType));
        return ERROR_WRONG_ITEM_TYPE;
    }

    unsigned short usCrystalId = (unsigned short)stGrid._stKey._uiItemID;
    CCrystalConfigData stConfigData;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetCrystalConfig(usCrystalId, stConfigData);
    CHECK_RETURN(iRet);

    //获取分解的价格
    if (stPlayerBaseInfo._i64Silver < stConfigData._iDecomPrice)
    {
        return ERROR_SILVER_LESS;
    }

    int iCnt = GetItemCount(stPlayerOnlineData._stUserStorage, ITEM_TYPE_CRYSTAL, usCrystalId);
    if (iCnt <= 0)
    {
        return ERROR_EQUIP_CRYSTAL_NONE;
    }

    CDropItemData stDropItemData;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropCrystalFrag(usCrystalId, stDropItemData);
    if (iRet)
    {
        CT_ERROR(("usCrystalId: %d, %d.\n", usCrystalId, iRet));
        return iRet;
    }

    CDropItem stDropItem;
    stDropItem.Drop(stDropItemData);
    if (!stDropItem.HasEnoughSpace(stPlayerOnlineData._uiGID))
    {
        return ERROR_BAG_WILL_FULL;
    }

    //先消耗,后添加
    iRet = TakeOutItem(stPlayerOnlineData._stUserStorage, usBagPos, 1);
    CHECK_RETURN(iRet);

    //加入到背包
    iRet = AddItem(stPlayerOnlineData._stUserStorage, ITEM_TYPE_CRYSTAL_FRAG, stDropItemData._usItemConfigID, stDropItemData._iItemCount);
    if (iRet)
    {
        CT_ERROR(("%d", iRet));
        return iRet;
    }

    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, stConfigData._iDecomPrice, 0);

    stResult._stKey._ucItemType = stDropItemData._ucItemType;
    stResult._stKey._uiItemID = stDropItemData._usItemConfigID;
    stResult._shCount = stDropItemData._iItemCount;
    return 0;
}

//合成不消耗金钱, 60级之前，可合成最高等级不超过6级的魔晶, (90, 7)  (110, 8)  (120, 9)  (130, 10)
int CStorageMgr::ComposeCrystalFrag(CUserStorage& stUserStorage, unsigned short usBagPos, CStorageGrid & stResult)
{
    CStorageGrid stGrid;
    int iRet = CMainCtrl::m_pstMain->m_stStorageMgr.GetGridInfoByPos(stUserStorage, true, usBagPos, stGrid);
    CHECK_RETURN(iRet);

    if (ITEM_TYPE_CRYSTAL_FRAG != stGrid._stKey._ucItemType )
    {
        CT_ERROR(("%d, %d", usBagPos, stGrid._stKey._ucItemType));
        return ERROR_WRONG_ITEM_TYPE;
    }

    if (stUserStorage.BagIsFull())
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    int iCnt = stGrid._shCount;
    if (iCnt < MAX_COMPOSE_CRYSTAL_FRAG_NUM)
    {
        return ERROR_LACK_CRYSTAL_FRAG;
    }

    CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY szKey;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr._stCrystalConfig.GetLevelOneCrystalSubType(szKey);
    CHECK_RETURN(iRet);

    CDropItemData stDropItemData;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetDropItemData(0, ITEM_TYPE_CRYSTAL, 0, szKey.GetBuffer(),
                                                             COMM_MOD, 1, stDropItemData);
    CHECK_RETURN(iRet);

    stResult._stKey._ucItemType = ITEM_TYPE_CRYSTAL;
    stResult._stKey._uiItemID = stDropItemData._usItemConfigID;
    stResult._shCount = stDropItemData._iItemCount;

    //先消耗,后添加
    iRet = TakeOutItem(stUserStorage, usBagPos, MAX_COMPOSE_CRYSTAL_FRAG_NUM);
    CHECK_RETURN(iRet);

    iRet = AddItem(stUserStorage, stDropItemData._ucItemType, stDropItemData._usItemConfigID, 1);
    CHECK_RETURN(iRet);

    return 0;
}

int CStorageMgr::OpenGift (CUserStorage& stUserStorage, unsigned int uiGiftId, unsigned int uiGid, CDropItem & stDropItem)
{
    int iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(uiGiftId, uiGid, stDropItem, false);
    if (iRet)
    {
        CT_ERROR(("%d, %d", uiGiftId, iRet));
        return iRet;
    }

    if (CMainCtrl::m_pstMain->m_stItemMgr.CheckBagFull(stUserStorage, stDropItem))
    {        
        return ERROR_BAG_WILL_FULL;
    }

    if (0 == stDropItem._iModule)
    {
        stDropItem.SetOssModule(OSS_MODULE_GIFT);
    }

    CMainCtrl::m_pstMain->m_stItemMgr.DropItem(0, uiGid, stDropItem);
    return 0;
}

int CStorageMgr::OneKeyOpenGiftInBag (CUserStorage& stUserStorage, unsigned short usBagPos, unsigned int uiGid, CDropItem & stDropItem, int & iOptRet)
{
    iOptRet = RET_OK;

    CStorageGrid stGrid;
    int iRet = GetGridInfoByPos(stUserStorage, true, usBagPos, stGrid);
    CHECK_RETURN(iRet);    
    
    int iNeedTakeOut = 0;
    CDropItem stTestDrop;
    for (int i = 0; i < stGrid._shCount; i++)
    {
        CDropItem stData;
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(stGrid._stKey._uiItemID, uiGid, stData, false);
        if (iRet)
        {               
            CT_ERROR(("%d, %d, %d", uiGid, stGrid._stKey._uiItemID, iRet));            
            break;
        }

        stTestDrop += stData;
        if (stTestDrop.Size() >= (MAX_DROP_ITEM_PER_TIME - 1))
        {            
            break;
        }
        
        if (false == stTestDrop.HasEnoughSpace(uiGid))
        {            
            iOptRet = ERROR_STORAGE_BAG_IS_FULL;
            break;            
        }

        stDropItem += stData;
        iNeedTakeOut += 1;
    }

    if (iNeedTakeOut > 0)
    {
        iRet = TakeOutItem(stUserStorage, usBagPos, iNeedTakeOut);
        if (iRet)
        {
            stDropItem.Clear();    //异常分支返回前清掉之前的结果，防止用户刷物品
            return iRet;
        }

        CT_TRACE(("%d, %d, %d, %d", uiGid, stGrid._stKey._ucItemType, stGrid._stKey._uiItemID, stGrid._shCount));

        stDropItem.SetOssModule(OSS_MODULE_GIFT);
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropItem(0, uiGid, stDropItem);
        if (iRet)
        {
            CT_ERROR(("%d, %d, %d, %d", uiGid, stGrid._stKey._ucItemType, stGrid._stKey._uiItemID, stGrid._shCount));
            stDropItem.Clear();
            return iRet;
        }
    }

    return RET_OK;
}

//打开礼包
int CStorageMgr::OpenGiftInBag (CUserStorage& stUserStorage, unsigned short usBagPos, unsigned int uiGid, CDropItem & stDropItem)
{
    CStorageGrid stGrid;
    int iRet = GetGridInfoByPos(stUserStorage, true, usBagPos, stGrid);
    if (iRet || stGrid._stKey._ucItemType != ITEM_TYPE_GIFT)
    {
        return ERROR_GRID_NOT_GIFT;
    }

    unsigned int uiGiftId = stGrid._stKey._uiItemID;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(uiGiftId, uiGid, stDropItem, false);
    if (iRet)
    {
        CT_WARNING(("%d, %d", uiGiftId, iRet));

        //对于等级礼包, 打开失败后尝试预览,让玩家能看到里面的内容
        CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(uiGiftId, uiGid, stDropItem, true);
        return iRet;
    }

    if (CMainCtrl::m_pstMain->m_stItemMgr.CheckBagFull(stUserStorage, stDropItem))
    {
        return ERROR_GIFT_BAG_GRID;
    }

    iRet = TakeOutItem(stUserStorage, usBagPos, 1);
    if (iRet)
    {
        CT_ERROR(("%d, %d", usBagPos, iRet));
        return iRet;
    }
    
    stDropItem.SetOssModule(OSS_MODULE_GIFT);
    CMainCtrl::m_pstMain->m_stItemMgr.DropItem(0, uiGid, stDropItem, false);

    //比比多味豆的获得精力时的特殊提示,前台展示用
    if (180 == uiGiftId)
    {
        for (int i = 0; i < stDropItem.Size(); i++)
        {        
            CDropItemData & stItemData = stDropItem._astDropItem[i];
            if (ITEM_TYPE_ENERGY == stItemData._ucItemType)
            {
                int iRandNum = CT_RANDOM_NUM->GetRand(100);
                switch (stItemData._iItemCount)
                {
                case 10:
                    stItemData._usItemConfigID = iRandNum / 25 + 1;
                    break;
                case 20:
                    stItemData._usItemConfigID = iRandNum / 33 + 5;
                    break;
                default:
                    stItemData._usItemConfigID = 0;
                }
            }
        }
    }


    CGiftConfigUnit stConfigData;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftConfig (uiGiftId, stConfigData);
    if (RET_OK == iRet && stConfigData._uiTipsType > 0)
    {
        MsgTips stTips;
        stTips.set_type(stConfigData._uiTipsType);       
        stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(uiGid));
        stDropItem.GetPBMsg(uiGid, *(stTips.mutable_bonus()));
        CMainCtrl::m_pstMain->SendOnlineTips (stTips);
    }

    return 0;
}

//预览礼包中物品
int CStorageMgr::PreViewGiftInfo (CUserStorage& stUserStorage, unsigned int uiGiftId, unsigned int uiGid,
                                  CDropItem & stGiftItem)
{
    int iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(uiGiftId, uiGid, stGiftItem, true);
    if (iRet)
    {
        CT_ERROR(("%d, %d, %d", uiGid, uiGiftId, iRet));
        return iRet;
    }

    return 0;
}

int CStorageMgr::ClearTime(CUserStorage& stUserStorage, unsigned short usBagPos, int iNewTime)
{
    return stUserStorage.ClearTime(usBagPos, iNewTime);
}

int CStorageMgr::CheckGiftAvail (CUserStorage& stUserStorage, unsigned int uiGid)
{
    CMainCtrl * pstMainCtrl = CMainCtrl::m_pstMain;
    short shLevel = 0;
    int iRet = pstMainCtrl->m_stRoleMgr.GetRoleLevel (uiGid, shLevel);
    CHECK_RETURN(iRet);

    bool bLevelGiftAvail = stUserStorage.IsLevelGiftAvail(shLevel);
    if (bLevelGiftAvail)
    {
        pstMainCtrl->m_stNotifyMgr.SendTips(uiGid, TIPS_TYPE_GIFT_AVAIL);
    }

    return 0;
}

void CStorageMgr::SendActStorageToFront(CPlayerDetailInfoEx1& stPlayerDetailEx1, 
        int iModuleID)
{
    CPlayerActStorage& stStorage = stPlayerDetailEx1._stActStorage;
    MsgAnsUserStorageInfo stAns;

    switch (iModuleID)
    {
    case ENM_ACT_STORAGE_LUCKY_DIAL:
        {
            stAns.set_gid(stPlayerDetailEx1._uiGID);
            stAns.set_storage_type(STORAGE_TYPE_LUCKY_DIAL);
            stAns.set_grid_total_num(stStorage._astLuckyDial.GetCount());
            stAns.set_grid_default_num(stStorage._astLuckyDial.GetCount());
            stAns.set_grid_unlocked_num(0);

            for (int i = 0; i < stStorage._astLuckyDial.Size(); ++i)
            {
                MsgGridItemInfo* pstGridInfo = stAns.add_grid_items();
                if (!pstGridInfo) {continue;}

                pstGridInfo->set_item_store_pos(i);
                pstGridInfo->set_item_type(
                    stStorage._astLuckyDial[i]._ucItemType);
                pstGridInfo->set_item_count(
                    stStorage._astLuckyDial[i]._iItemCount);
                pstGridInfo->set_item_config_id(
                    stStorage._astLuckyDial[i]._usItemConfigID);
            }
        }
        break;
    
    default:
        return;
    }

    CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerDetailEx1._uiGID,
        ID_MAIN_GET_USER_STORAGE_INFO, stAns, false);
}

int CStorageMgr::AddOneItemToActStorage(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CDropItemData& stDropItemData, int iModuleID)
{
    if (stDropItemData._ucItemType < ITEM_TYPE_MIN ||
        stDropItemData._ucItemType > ITEM_TYPE_MAX)
    {
        return ERROR_ITEM_INVALID_DROP_ITEM_TYPE;
    }

    int iRet = 0;
    CPlayerActStorage& stStorage = stPlayerDetailEx1._stActStorage;

    switch (iModuleID)
    {
    case ENM_ACT_STORAGE_LUCKY_DIAL:
        {
            for (int i = 0; i < stStorage._astLuckyDial.Size(); ++i)
            {
                if (stStorage._astLuckyDial[i]._ucItemType ==
                        stDropItemData._ucItemType &&
                    stStorage._astLuckyDial[i]._usItemConfigID ==
                        stDropItemData._usItemConfigID)
                {
                    stStorage._astLuckyDial[i]._iItemCount +=
                        stDropItemData._iItemCount;
                    return 0;
                }
            }

            iRet = stStorage._astLuckyDial.AddOneItem(stDropItemData);
            if (iRet < 0)
            {
                CT_ERROR(("Role(%u) Add Lucky Dial Item(%d %d %d) Error(%d)",
                    stPlayerDetailEx1._uiGID, stDropItemData._ucItemType,
                    stDropItemData._usItemConfigID,
                    stDropItemData._iItemCount));
            }
        }
        break;
    
    default:
        return ERROR_ACT_STORAGE_UNKNOW_MODULE;
    }

    return 0;
}

int CStorageMgr::AddItemToActStorage(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CDropItem& stDropItem, int iModuleID)
{
    if (stDropItem._astDropItem.Size() <= 0)
    {
        return 0;
    }

    int iRet = 0;

    switch (iModuleID)
    {
    case ENM_ACT_STORAGE_LUCKY_DIAL:
        {
            for (int i = 0; i < stDropItem._astDropItem.Size(); ++i)
            {
                iRet = AddOneItemToActStorage(stPlayerDetailEx1,
                    stDropItem._astDropItem[i], iModuleID);
                if (iRet)
                {
                    CT_ERROR(("Role(%u) Lucky Dial Item(%d %d %d) Error(%d)",
                        stPlayerDetailEx1._uiGID,
                        stDropItem._astDropItem[i]._ucItemType,
                        stDropItem._astDropItem[i]._usItemConfigID,
                        stDropItem._astDropItem[i]._iItemCount));
                }
            }
        }
        break;
    
    default:
        return ERROR_ACT_STORAGE_UNKNOW_MODULE;
    }

    CMainCtrl::m_pstMain->m_stRewardBackMgr.UpdateDetailEx1ToDB(
        stPlayerDetailEx1);

    return 0;
}

int CStorageMgr::GetActStorageItem(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CPlayerOnlineData& stPlayerOnline, MsgReqActStorage& stReq,
        MsgAnsActStorage& stAns)
{
    if (!stReq.has_req_type() || !stReq.has_item_pos())
    {
        CT_WARNING((""));
        return RET_REQ_NOT_COMPLETE;
    }

    int iRet = 0;
    int iItemPos = stReq.item_pos();

    CDropItem stDropItem;
    CPlayerActStorage& stStorage = stPlayerDetailEx1._stActStorage;

    switch (stReq.req_type())
    {
    case ENM_ACT_STORAGE_LUCKY_DIAL:
        {
            if (stStorage._astLuckyDial.Size() <= 0)
            {
                return 0;
            }

            if (iItemPos < 0 || iItemPos > stStorage._astLuckyDial.Size())
            {
                return ERROR_STORAGE_ITEM_NOT_EXIST;
            }

            if (iItemPos == 0)
            {
                for (int i = 0; i < stStorage._astLuckyDial.Size(); ++i)
                {
                    stDropItem.Drop(stStorage._astLuckyDial[i]);
                }
            }
            else
            {
                stDropItem.Drop(stStorage._astLuckyDial[iItemPos - 1]);
            }
        }
        break;
    
    default:
        return ERROR_ACT_STORAGE_UNKNOW_MODULE;
    }

    if (CMainCtrl::m_pstMain->m_stItemMgr.CheckBagFull(
            stPlayerOnline._stUserStorage, stDropItem))
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    switch (stReq.req_type())
    {
    case ENM_ACT_STORAGE_LUCKY_DIAL:
        {
            if (iItemPos == 0)
            {
                stStorage._astLuckyDial.Clear();
            }
            else
            {
                stStorage._astLuckyDial.DelOneItem(iItemPos - 1);
            }

            SendActStorageToFront(stPlayerDetailEx1,ENM_ACT_STORAGE_LUCKY_DIAL);
        }
        break;
    
    default:
        return ERROR_ACT_STORAGE_UNKNOW_MODULE;
    }

    //发送物品
    stDropItem.SetOssModule(OSS_MODULE_LUCKY_DIAL);
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL,
        stPlayerDetailEx1._uiGID, stDropItem);
    CT_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stRewardBackMgr.UpdateDetailEx1ToDB(
        stPlayerDetailEx1);

    return 0;
}

